# -- coding:utf8 --
"""
获取屏幕触点的程序，包含两部分：
1、获取屏幕触点信息的类
2、屏幕触点信息线程类，将触点信息进一步处理并发出产生事件
注释中的“事件”和“信号”可以理解为一个意义
"""

import signal

import usb.core
from PyQt4 import QtGui, QtCore

class ScreenPoint:
    """
    获取屏幕触点基本信息
    """
    def __init__(self, VID, PID):
        self.Height = 798  # 屏幕尺寸mm
        self.Width = 342
        self.pixx = 1080  # 屏幕尺寸pix
        self.pixy = 1920

        self.PointNum = 32767  # 屏幕点坐标取值范围是0000-7fff即0-32767
        self.PointHeight = self.Height * 1.0 / self.PointNum  # 点大小/mm
        self.PointWidth = self.Width * 1.0 / self.PointNum
        self.pointpixx = self.pixx * 1.0 / self.PointNum  # 点大小/pix
        self.pointpixy = self.pixy * 1.0 / self.PointNum

        # 存储每帧中点的信息
        # 每组数据依次存储x坐标毫米值，y坐标毫米值，x坐标像素点值，y坐标像素点值
        self.point = []
        self.VID = VID  # 设备VID
        self.PID = PID  # 设备PID
        self.dev = usb.core.find(idVendor=self.VID, idProduct=self.PID)  # 以vid和pid获取设备信息
        self.interface = 2

    def connect(self):
        self.cfg = self.dev.get_active_configuration()  # 获取设备设置
        self.endpoint = self.dev[0][(self.interface,0)][0]  # usb的endpoint

        if self.dev.is_kernel_driver_active(self.interface) is True:
            self.dev.detach_kernel_driver(self.interface)              # 设备被占用时解出占用

    def getdata(self):
        self.point = []
        try:
            data = self.dev.read(self.endpoint.bEndpointAddress,self.endpoint.wMaxPacketSize)  # 从endpoint读取数据

            # 对数据进行整理
            # 数据第i*10+3存储x坐标低位，第i*10+4存储x坐标高位，第i*10+5存储y坐标低位，第i*10+6存储y坐标高位
            # 坐标取值范围是0000-7fff即0-32767
            # 若为6-10点触摸，则会产生两帧数据，每帧5个触点shuju
            for i in range(data[60]):
                tmppoint = []  # 存放读到的单个点
                tmppoint.append((int)((self.PointNum - (data[5 + (i % 5)*10 + 10] * 256 + data[6 + (i % 5)*10 + 10])) * self.PointWidth))  #计算距离时因为屏幕竖着放，跟屏幕原本坐标不一致，坐标进行了一定转换
                tmppoint.append((int)((self.PointNum - (data[3 + (i % 5)*10 + 10] * 256 + data[4 + (i % 5)*10 + 10])) * self.PointHeight))
                tmppoint.append((int)((self.PointNum - (data[5 + (i % 5)*10 + 10] * 256 + data[6 + (i % 5)*10 + 10])) * self.pointpixx))  #计算像素点时坐标变换，原点在左上角，与计算距离不同
                tmppoint.append((int)((data[3 + (i % 5)*10 + 10] * 256 + data[4 + (i % 5)*10 + 10]) * self.pointpixy))
                self.point.append(tmppoint)
            return True
        except usb.core.USBError as e:  #未读到数据报错
            if e.args == ('Operation timed out',):
                data = None
                return False
    
    def release(self):
        usb.util.release_interface(self.dev,self.interface)  #释放设备
        try:
            self.dev.attach_kernel_driver(self.interface)  #激活设备
        except usb.core.USBError:
            print ("设备已处于激活状态")

class PointThread(QtCore.QThread):    
    """
    获取屏幕触点的线程，继承自QtCore.QThread
    """
    Point = QtCore.pyqtSignal(bool,list)    #屏幕触点信号，信号传递一个bool型参数，表示是否有数据，一个list型参数，表示触点信息

    def __init__(self, TouchPoint, parent = None):
        super(PointThread, self).__init__(parent)
        self.point = []    #屏幕触点坐标
        self.StartFlag = True    #线程运行标志
        self.TouchPoint = TouchPoint

    def run(self):
        """
        重写run函数，当主程序调用线程的start方法时该方法自动执行
        """
        while self.StartFlag:
            a = self.TouchPoint.getdata()    # 获取触点信息
            if a == True:    # 屏幕有触点
                # print (self.TouchPoint.point)
                for i in range(len(self.TouchPoint.point)):    # 循环取数据
                    self.point = self.TouchPoint.point[i]    # 赋值坐标，一个点一个点的传输
                    self.Point.emit(True,self.point)    # 发出信号
            else:
                self.Point.emit(False, self.point)    # 发出信号，无触点
                # print("No Data")
